/*
 * OptimizationObject.h
 *
 *      Author: Jerome RD Soine and Christoph A Brand
 *      Institution: Schwarz goup, Institute for Theoretical Physics, Heidelberg University, Germany
 */

#ifndef OPTIMIZATIONOBJECT_H_
#define OPTIMIZATIONOBJECT_H_

#include "include/base/utility/DataContainer.h"
#include "include/base/cell_models/ACM/ActiveCableModel.h"
#include "include/base/substrate_models/FEM/FEMCalc.h"
#include "include/core/comparator/L2Comparator.h"

#include <base/parameter_handler.h>
#include <string>

class OptimizationObject
{
public:
	static const int METHOD_STEEPEST_DESCENT = 1;
	static const int METHOD_CONJUGATED_GRADIENT = 2;
	static const int METHOD_CONJUGATED_GRADIENT_NT_FIRST = 3;
	static const int METHOD_CONJUGATED_GRADIENT_NT_LAST = 4;
	static const int METHOD_SIMPLEX = 5;
	static const int METHOD_SIMPLEX_ANNEALING = 6;
	static const int METHOD_FIXED_NT_CG = 7;
	static const int METHOD_SAMPLE_AROUND_NT_CG = 7;

	OptimizationObject(string parameter_file);

	OptimizationObject(string project_folder, string cell_mesh, string disp_file, double young, double poisson, Point<3> fem_mesh_dimension, unsigned int degree_of_refinement);

	~OptimizationObject();

	void initializeWorkerManager(string acm_filename, string acm_output_folder, vector<double> parameter);

	unsigned int get_n_parameters();

	Point<3> get_mesh_point1(){return *mesh_point1; };
	Point<3> get_mesh_point2(){return *mesh_point2; };

	int get_n_optimization_steps(){return n_optimization_steps;};
	unsigned int get_n_threads(){return n_threads;};

	bool is_preshifting_enabled(){return preshifting_enabled;};
	bool is_preconditioning_enabled(){return preconditioning_enabled;};
	bool is_simulated_data_enabled(){return simulated_data;};
	bool is_tension_input_enabled(){return tension_input;}
	bool is_generate_results(){return generate_results;};
	bool is_decrease_network_tension(){return decrease_network_tension;};

	string get_cell_mesh_file();
	string get_project_folder();
	string get_disp_file();
	string get_tension_file(){return tension_file;};
	string get_shape_file(){return shape_file;};
	int get_optimization_method();

	double get_young_mod();
	double get_poisson_ratio();
	double get_reg_param(){return reg_param;};

	Point<3> get_mesh_size();

	double get_initial_temperature();
	double get_simplex_step_width();
	double get_annealing_parameter();

	void set_cell_mesh_file(string filename){cell_mesh=filename;};
	void set_disp_file(string disp){disp_file = disp;}

	unsigned int get_degree_of_refinement();
	unsigned int get_n_sf_steps_per_network_tension_adjustment(){return n_sf_steps_per_network_tension_adjustment;};

	void print_parameters();

	void save_parameters(string filename);
	double get_known_network_tension(){return known_network_tension;};
	vector<double> get_cutting_point1(){return cutting_point1;};
	vector<double> get_cutting_point2(){return cutting_point2;};

private:

	void declare_parameter_handler();

	void define_parameters_from_handler();

	ParameterHandler* parameter_handler;

	string project_folder;
	string cell_mesh;
	string disp_file;
	string tension_file;
	string shape_file;

	double young_mod;
	double poisson_ratio;
	double reg_param;
	double known_network_tension;

	int image_width;
	int image_height;
	int substrate_depth;

	int boundary_extension;

	bool preshifting_enabled;
	bool preconditioning_enabled;
	bool simulated_data;
	bool tension_input;
	bool generate_results;
	bool decrease_network_tension;

	double initial_annnealing_temp;
	double annealing_parameter;
	double simplex_step_width;


	int n_optimization_steps;

	int optimization_method;

	Point<3>* mesh_point1;
	Point<3>* mesh_point2;

	Point<3> mesh_size;

	unsigned int deg_of_ref;

	unsigned int n_threads;
	unsigned int n_sf_steps_per_network_tension_adjustment;

	vector<double> cutting_point1, cutting_point2;
};

#endif /* OPTIMIZATIONOBJECT_H_ */
